package com.summer.filesync.manager.service;

import com.summer.filesync.database.dao.FileMetadataDAO;
import com.summer.filesync.model.FileMetadata;
import com.summer.filesync.model.manager.*;
import com.summer.filesync.util.Logger;
import java.io.File;
import java.util.*;
import java.util.stream.Collectors;

/** 文件分析服务 提供文件分析和统计功能 */
public class FileAnalysisService {
  private static final Logger logger = Logger.getLogger(FileAnalysisService.class);

  private final FileMetadataDAO fileMetadataDAO;

  public FileAnalysisService(FileMetadataDAO fileMetadataDAO) {
    this.fileMetadataDAO = fileMetadataDAO;
  }

  /** 查找重复文件 */
  public List<DuplicateFileGroup> findDuplicateFiles() {
    logger.info("开始分析重复文件...");

    try {
      List<FileMetadata> allFiles = fileMetadataDAO.findAll();

      // 按文件校验和分组（使用checksum而不是fileHash以兼容现有数据库）
      Map<String, List<FileMetadata>> checksumGroups =
          allFiles.stream()
              .filter(f -> !f.isDirectory() && f.getChecksum() != null)
              .collect(Collectors.groupingBy(FileMetadata::getChecksum));

      // 找出重复的文件组
      List<DuplicateFileGroup> duplicateGroups =
          checksumGroups.entrySet().stream()
              .filter(entry -> entry.getValue().size() > 1)
              .map(entry -> new DuplicateFileGroup(entry.getKey(), entry.getValue()))
              .sorted((g1, g2) -> Long.compare(g2.getWastedSpace(), g1.getWastedSpace()))
              .collect(Collectors.toList());

      logger.info("发现 " + duplicateGroups.size() + " 组重复文件");
      return duplicateGroups;

    } catch (Exception e) {
      logger.error("分析重复文件失败", e);
      return new ArrayList<>();
    }
  }

  /** 分析存储使用情况 */
  public StorageAnalysisResult analyzeStorageUsage() {
    logger.info("开始分析存储使用情况...");

    StorageAnalysisResult result = new StorageAnalysisResult();

    try {
      List<FileMetadata> allFiles = fileMetadataDAO.findAll();

      // 基本统计
      long totalSize =
          allFiles.stream()
              .filter(f -> !f.isDirectory())
              .mapToLong(FileMetadata::getFileSize)
              .sum();

      long fileCount = allFiles.stream().filter(f -> !f.isDirectory()).count();

      long directoryCount = allFiles.stream().filter(FileMetadata::isDirectory).count();

      result.setUsedSpace(totalSize);
      result.setFileCount(fileCount);
      result.setDirectoryCount(directoryCount);

      // 找出最大文件
      Optional<FileMetadata> largestFile =
          allFiles.stream()
              .filter(f -> !f.isDirectory())
              .max(Comparator.comparing(FileMetadata::getFileSize));

      if (largestFile.isPresent()) {
        result.setLargestFileSize(largestFile.get().getFileSize());
        result.setLargestFilePath(largestFile.get().getFilePath());
      }

      // 按扩展名统计
      Map<String, Long> extensionSizes = new HashMap<>();
      Map<String, Integer> extensionCounts = new HashMap<>();

      for (FileMetadata file : allFiles) {
        if (!file.isDirectory()) {
          String extension = getFileExtension(file.getFilePath());
          extensionSizes.merge(extension, file.getFileSize(), Long::sum);
          extensionCounts.merge(extension, 1, Integer::sum);
        }
      }

      result.setExtensionSizes(extensionSizes);
      result.setExtensionCounts(extensionCounts);

      // 计算磁盘使用百分比（简化版本）
      File[] roots = File.listRoots();
      if (roots.length > 0) {
        File root = roots[0];
        long totalSpace = root.getTotalSpace();
        long freeSpace = root.getFreeSpace();
        long usedSpace = totalSpace - freeSpace;

        result.setTotalSpace(totalSpace);
        result.setFreeSpace(freeSpace);
        result.setUsedSpacePercentage((double) usedSpace / totalSpace * 100);
      }

      logger.info("存储分析完成: " + fileCount + " 个文件，总大小 " + formatBytes(totalSize));

    } catch (Exception e) {
      logger.error("分析存储使用情况失败", e);
    }

    return result;
  }

  /** 分析文件类型分布 */
  public FileTypeDistribution analyzeFileTypeDistribution() {
    logger.info("开始分析文件类型分布...");

    try {
      List<FileMetadata> allFiles = fileMetadataDAO.findAll();

      Map<String, Integer> typeCounts = new HashMap<>();
      Map<String, Long> typeSizes = new HashMap<>();

      int totalFileCount = 0;
      long totalSize = 0;

      for (FileMetadata file : allFiles) {
        if (!file.isDirectory()) {
          String extension = getFileExtension(file.getFilePath());
          String fileType = getFileTypeDescription(extension);

          typeCounts.merge(fileType, 1, Integer::sum);
          typeSizes.merge(fileType, file.getFileSize(), Long::sum);

          totalFileCount++;
          totalSize += file.getFileSize();
        }
      }

      logger.info("文件类型分析完成: " + typeCounts.size() + " 种类型");
      return new FileTypeDistribution(typeCounts, typeSizes, totalFileCount, totalSize);

    } catch (Exception e) {
      logger.error("分析文件类型分布失败", e);
      return new FileTypeDistribution(new HashMap<>(), new HashMap<>(), 0, 0);
    }
  }

  /** 查找大文件 */
  public List<FileMetadata> findLargeFiles(long minSizeBytes, int limit) {
    logger.info("查找大于 " + formatBytes(minSizeBytes) + " 的文件...");

    try {
      List<FileMetadata> allFiles = fileMetadataDAO.findAll();

      List<FileMetadata> largeFiles =
          allFiles.stream()
              .filter(f -> !f.isDirectory())
              .filter(f -> f.getFileSize() >= minSizeBytes)
              .sorted((f1, f2) -> Long.compare(f2.getFileSize(), f1.getFileSize()))
              .limit(limit)
              .collect(Collectors.toList());

      logger.info("找到 " + largeFiles.size() + " 个大文件");
      return largeFiles;

    } catch (Exception e) {
      logger.error("查找大文件失败", e);
      return new ArrayList<>();
    }
  }

  /** 查找旧文件 */
  public List<FileMetadata> findOldFiles(long olderThanDays, int limit) {
    logger.info("查找超过 " + olderThanDays + " 天未修改的文件...");

    try {
      long cutoffTime = System.currentTimeMillis() - (olderThanDays * 24 * 60 * 60 * 1000);

      List<FileMetadata> allFiles = fileMetadataDAO.findAll();

      List<FileMetadata> oldFiles =
          allFiles.stream()
              .filter(f -> !f.isDirectory())
              .filter(f -> f.getLastModified() < cutoffTime)
              .sorted((f1, f2) -> Long.compare(f1.getLastModified(), f2.getLastModified()))
              .limit(limit)
              .collect(Collectors.toList());

      logger.info("找到 " + oldFiles.size() + " 个旧文件");
      return oldFiles;

    } catch (Exception e) {
      logger.error("查找旧文件失败", e);
      return new ArrayList<>();
    }
  }

  /** 获取文件扩展名 */
  private String getFileExtension(String filePath) {
    if (filePath == null || filePath.isEmpty()) {
      return "无扩展名";
    }

    int lastDotIndex = filePath.lastIndexOf('.');
    if (lastDotIndex == -1 || lastDotIndex == filePath.length() - 1) {
      return "无扩展名";
    }

    return filePath.substring(lastDotIndex + 1).toLowerCase();
  }

  /** 获取文件类型描述 */
  private String getFileTypeDescription(String extension) {
    if (extension == null || extension.equals("无扩展名")) {
      return "无扩展名文件";
    }

    switch (extension.toLowerCase()) {
      case "txt", "log", "md", "readme":
        return "文本文件";
      case "doc", "docx", "pdf", "rtf":
        return "文档文件";
      case "jpg", "jpeg", "png", "gif", "bmp", "svg":
        return "图像文件";
      case "mp3", "wav", "flac", "m4a", "aac":
        return "音频文件";
      case "mp4", "avi", "mkv", "mov", "wmv":
        return "视频文件";
      case "zip", "rar", "7z", "tar", "gz":
        return "压缩文件";
      case "java", "class", "jar":
        return "Java文件";
      case "py", "pyc":
        return "Python文件";
      case "js", "html", "css", "json":
        return "Web文件";
      case "exe", "msi", "deb", "rpm":
        return "可执行文件";
      default:
        return extension.toUpperCase() + "文件";
    }
  }

  /** 格式化字节数 */
  private String formatBytes(long bytes) {
    if (bytes < 1024) return bytes + " B";
    int exp = (int) (Math.log(bytes) / Math.log(1024));
    String pre = "KMGTPE".charAt(exp - 1) + "";
    return String.format("%.1f %sB", bytes / Math.pow(1024, exp), pre);
  }
}
